package com.cleaningcloud.cld.service.impl;

import com.cleaningcloud.cld.api.domain.CldStaff;
import com.cleaningcloud.cld.domain.CldClasses;
import com.cleaningcloud.cld.domain.CldLeave;
import com.cleaningcloud.cld.domain.CldPayDetails;
import com.cleaningcloud.cld.domain.dto.CldAttendanceDto;
import com.cleaningcloud.cld.domain.dto.CldLeaveDto;
import com.cleaningcloud.cld.domain.dto.CldPayDetailsDto;
import com.cleaningcloud.cld.domain.dto.CldProjectPostDto;
import com.cleaningcloud.cld.domain.vo.CldAttendanceVo;
import com.cleaningcloud.cld.domain.vo.CldLeaveVo;
import com.cleaningcloud.cld.domain.vo.CldProjectPostSetVo;
import com.cleaningcloud.cld.mapper.CldAttendanceMapper;
import com.cleaningcloud.cld.mapper.CldClassesMapper;
import com.cleaningcloud.cld.mapper.CldLeaveMapper;
import com.cleaningcloud.cld.service.ICldAttendanceService;
import com.cleaningcloud.cld.service.ICldLeaveService;
import com.cleaningcloud.cld.service.ICldPayDetailsService;
import com.cleaningcloud.cld.service.ICldProjectPostService;
import com.cleaningcloud.cld.utils.AttendanceConversionUtils;
import com.cleaningcloud.common.core.utils.DateUtils;
import com.cleaningcloud.common.security.utils.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 请假管理Service业务层处理
 *
 * @author cleaningcloud
 * @date 2024-11-08
 */
@Service
public class CldLeaveServiceImpl implements ICldLeaveService {
    @Autowired
    private CldLeaveMapper cldLeaveMapper;

    @Autowired
    private ICldAttendanceService cldAttendanceService;

    @Autowired
    private CldAttendanceMapper cldAttendanceMapper;

    @Autowired
    private CldClassesMapper cldClassesMapper;

    @Autowired
    private ICldPayDetailsService cldPayDetailsService;

    @Autowired
    private ICldProjectPostService cldProjectPostService;


    /**
     * 查询请假管理
     *
     * @param leaveId 请假管理主键
     * @return 请假管理
     */
    @Override
    public CldLeaveVo selectCldLeaveByLeaveId(Long leaveId) {
        return cldLeaveMapper.selectCldLeaveByLeaveId(leaveId);
    }

    /**
     * 查询请假管理列表
     *
     * @param cldLeave 请假管理
     * @return 请假管理
     */
    @Override
    public List<CldLeaveVo> selectCldLeaveList(CldLeaveDto cldLeave) {
        return cldLeaveMapper.selectCldLeaveList(cldLeave);
    }



    /**
     * 新增请假管理
     *
     * @param cldLeave 请假管理
     * @return 结果
     */
    @Override
    @Transactional
    public int insertCldLeave(CldLeaveDto cldLeave) {
        List<CldLeave> cldLeaveList = new ArrayList<>();
        cldLeave.setCreateTime(DateUtils.getNowDate());
        cldLeave.setApproveStatus(1L);
        cldLeave.setCreateId(SecurityUtils.getUserId());
        cldLeave.setCreateName(SecurityUtils.getUsername());
        cldLeave.setFlag(0L);
        // 结束时间必须大于开始时间
        if(DateUtils.dateToLocalTime(cldLeave.getEndTime()).isBefore(DateUtils.dateToLocalTime(cldLeave.getStartTime()))){
            throw new RuntimeException("请假结束时间必须大于开始时间！");
        }
        // 员工集合不为空时
        if (cldLeave.getStaffList() != null && !cldLeave.getStaffList().isEmpty()) {
            for (CldStaff cldStaff : cldLeave.getStaffList()) {
                CldLeave leave = new CldLeave();
                BeanUtils.copyProperties(cldLeave, leave);
                leave.setStaffId(cldStaff.getStaffId());
                // 查询该员工当天是否有请假信息
                List<CldLeaveVo> checkLeave = cldLeaveMapper.checkwhetherLeave(leave);
                if (!checkLeave.isEmpty()) {
                    throw new RuntimeException("[" + checkLeave.get(0).getStaffName() + "]已在[" + DateUtils.dateTime(checkLeave.get(0).getStartTime()) + "至" + DateUtils.dateTime(checkLeave.get(0).getEndTime()) + "]时间段请假！");
                }
                cldLeaveList.add(leave);
            }
        } else {
            // 查询该员工当天是否有请假信息
            List<CldLeaveVo> checkLeave = cldLeaveMapper.checkwhetherLeave(cldLeave);
            if (!checkLeave.isEmpty()) {
                throw new RuntimeException("[" + checkLeave.get(0).getStaffName() + "]已在[" + DateUtils.dateTime(checkLeave.get(0).getStartTime()) + "]至[" + DateUtils.dateTime(checkLeave.get(0).getEndTime()) + "]时间段请假！");
            }
            cldLeaveList.add(cldLeave);
        }
        return cldLeaveMapper.batchInsertCldLeave(cldLeaveList);
    }

    /**
     * 修改请假管理
     *
     * @param cldLeave 请假管理
     * @return 结果
     */
    @Override
    public int updateCldLeave(CldLeave cldLeave) {
        cldLeave.setApproveStatus(1L);
        return cldLeaveMapper.updateCldLeave(cldLeave);
    }

    @Override
    @Transactional
    public int auditCldLeave(CldLeave cldLeave) {
        CldLeave leave = cldLeaveMapper.selectCldLeaveByLeaveId(cldLeave.getLeaveId());
        if (leave == null) {
            throw new RuntimeException("请假信息查询失败");
        }
        leave.setApproveTime(DateUtils.getNowDate());
        leave.setApproveId(SecurityUtils.getUserId());
        leave.setApproveName(SecurityUtils.getUsername());
        leave.setApproveStatus(cldLeave.getApproveStatus());
        // 审核拒绝
        if (cldLeave.getApproveStatus() == 2) {
            leave.setResultReason(cldLeave.getResultReason());
        }
        // 审核通过
        if (cldLeave.getApproveStatus() == 3) {
            // 查询考勤表 修改当条考勤记录为请假
            CldAttendanceDto attQuery = new CldAttendanceDto();
            // 查询员工班次信息
            CldClasses cldClasses = cldClassesMapper.selectCldClassesByProjectIdAndStaffId(leave.getProjectId(), leave.getStaffId());
            if (cldClasses == null) {
                throw new RuntimeException("该员工尚未配置班次信息！");
            }
            LocalDate startDate = leave.getStartTime().toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDate(); // 转换开始日期
            attQuery.setProjectId(leave.getProjectId());
            attQuery.setStaffId(leave.getStaffId());
            attQuery.setAttendanceYear(startDate.getYear());
            attQuery.setAttendanceMonth(startDate.getMonthValue());
            attQuery.setAttendanceDay(startDate.getDayOfMonth());
            List<CldAttendanceVo> attendanceList = cldAttendanceService.selectCldAttendanceList(attQuery);
            if (!attendanceList.isEmpty()) {
                CldAttendanceVo attendance = attendanceList.get(0);
                if (attendance.getIsLeave() == 0) {
                    attendance.setIsLeave(1L);
                    attendance.setLeaveStartTime(DateUtils.dateToLocalTime(leave.getStartTime()));
                    attendance.setLeaveEndTime(DateUtils.dateToLocalTime(leave.getEndTime()));
                    cldAttendanceMapper.updateCldAttendance(attendance);
                    // 查询员工岗位及薪资配置
                    CldProjectPostDto query = new CldProjectPostDto();
                    query.setStaffId(leave.getStaffId());
                    query.setProjectId(leave.getProjectId());
                    query.setIsMasterDuits(1L);
                    List<CldProjectPostSetVo> cldProjectPost = cldProjectPostService.selectCldProjectPostList(query);
                    // 覆盖请假时间
                    attendance.setLeaveStartTime(DateUtils.dateToLocalTime(leave.getStartTime()));
                    attendance.setLeaveEndTime(DateUtils.dateToLocalTime(leave.getEndTime()));
                    // 计算请假扣款工资
//                    cldPayDetailsService.insertCldPayDetails(AttendanceConversionUtils.LeaveSalaryCalculate(attendance, cldProjectPost.get(0)));
                    cldAttendanceService.updateCldAttendance(attendance);
                }
            }
        }
        // 撤销请假
        if (cldLeave.getApproveStatus() == 4) {
            LocalDate startDate = leave.getStartTime().toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDate(); // 转换开始日期
            Calendar calendar = Calendar.getInstance();
            if ((startDate.getYear() <= calendar.get(Calendar.YEAR)) && (startDate.getMonthValue() <= (calendar.get(Calendar.MONTH) + 1))
                && (startDate.getDayOfMonth() <= calendar.get(Calendar.DAY_OF_MONTH))){
                throw new RuntimeException("撤销功能只限于请假开始时间大于当前时间");
            }else{
                leave.setApproveStatus(1L);
                if(null != leave.getResultReason()){
                    leave.setResultReason(leave.getResultReason()+"(撤销操作)");
                }else{
                    leave.setResultReason("(撤销操作)");
                }
            }
        }
        return cldLeaveMapper.updateCldLeave(leave);
    }

    /**
     * 批量删除请假管理
     *
     * @param leaveIds 需要删除的请假管理主键
     * @return 结果
     */
    @Override
    public int deleteCldLeaveByLeaveIds(Long[] leaveIds) {
        return cldLeaveMapper.deleteCldLeaveByLeaveIds(leaveIds);
    }

    /**
     * 删除请假管理信息
     *
     * @param leaveId 请假管理主键
     * @return 结果
     */
    @Override
    public int deleteCldLeaveByLeaveId(Long leaveId) {
        return cldLeaveMapper.deleteCldLeaveByLeaveId(leaveId);
    }
}
